// @Title       main2.go
// @Description //TODO
// @Author      mamahaha125
// @Data        2023/8/30 22:23
package main

import (
	"fmt"
	"io"
	"net"
	"net/url"
	"regexp"
	"sync"
)

var (
	buf                = make([]byte, 2048)
	req                = make([]byte, 2048)
	replacedHostHeader []byte
)

type Proxyurl struct {
	List map[string]*Proxy
}

type Proxy struct {
	name      string
	LocalPort int
	url       string
	Conn      net.Conn
	Type      string
	*sync.RWMutex
}

func waf(data []byte) []byte {
	return data
}

// 处理SSH请求
func SSH() {
	return
}

// 处理HTTP请求
func HttpOrHttps(ClientConn net.Conn, urls string) {
	ProxyConn, err := net.Dial("tcp", urls)
	if err != nil {
		fmt.Println("访问网址失败")
	}
	defer ClientConn.Close()
	defer ProxyConn.Close()

	_, err = ProxyConn.Write(replacedHostHeader)
	if err != nil {
		fmt.Println("代理失败")
	}

	if _, err = io.CopyBuffer(ClientConn, ProxyConn, buf); err != nil {
		fmt.Println("代理传回数据失败")
	}
	fmt.Printf("回传数据给%s成功", ClientConn.LocalAddr())
	return
}

// 处理访问句柄
func SocketSend(conn net.Conn, proxy *Proxy) {

	_, _ = conn.Read(req)
	req = waf(req)

	switch {
	case proxy.Type == "ssh":
		SSH()
	case proxy.Type == "http":
		// 替换host
		hostRegex := regexp.MustCompile(`Host: (\S+)`)
		replacedHostHeader = hostRegex.ReplaceAll(req, []byte("Host: "+proxy.url))
		if _, err := url.Parse(proxy.url); err == nil {
			proxy.url = proxy.url + ":http"
		}
		HttpOrHttps(conn, proxy.url)
	}
}

// 开启反向代理监听
func SocketLoop(name string, proxy *Proxy) {
	listen, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", proxy.LocalPort))
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("Proxy for %s is running by port %d\n", name, proxy.LocalPort)
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println(err)
		}

		go SocketSend(conn, proxy)
	}

}

func main() {
	Baidu := &Proxy{
		Conn:      nil,
		url:       "www.baidu.com",
		LocalPort: 8999,
		Type:      "ssh",
	}
	Zhihu := &Proxy{
		Conn:      nil,
		url:       "www.zhihu.com",
		LocalPort: 8988,
		Type:      "http",
	}
	ssh := &Proxy{
		Conn:      nil,
		url:       "192.168.200.101:22",
		LocalPort: 2002,
		Type:      "ssh",
	}

	lists := &Proxyurl{
		List: map[string]*Proxy{
			"baidu": Baidu,
			"zhihu": Zhihu,
			"ssh":   ssh,
		},
	}

	for k, v := range lists.List {
		go SocketLoop(k, v)
	}
	select {}
}

//func SSH(ClientSSH net.Conn, data []byte, remotename string, command string) {
//	config := &ssh.ClientConfig{
//		User: "root",
//		Auth: []ssh.AuthMethod{
//			ssh.Password("mayongxian"),
//		},
//		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
//	}
//	conn, err := ssh.Dial("tcp", remotename, config)
//	if err != nil {
//		fmt.Println(err)
//	}
//	defer conn.Close()
//
//	session, err := conn.NewSession()
//	if err != nil {
//		err = fmt.Errorf("ssh new session error %v", err)
//		return
//	}
//	defer session.Close()
//
//	outPut, err = session.Output(command)
//	if err != nil {
//		err = fmt.Errorf("run command %s on host %s error %v", command, host, err)
//	}
//	io.Copy()
//}
